import sys
import time
from collections import OrderedDict
from PyMimircache import Cachecow
from PyMimircache.cache.lru import LRU
from PyMimircache.cacheReader.requestItem import Req

c=Cachecow()

#通过运行三层存储层次，获得每层执行访问的相应的时间
#运行此脚本时格式为 'python 脚本名 trace路径'
#定义trace路径,获取reader
# trace_path="traces/2_pools.txt"
# trace_path="traces/test.txt"
trace_path=sys.argv[1]
reader=c.open(trace_path)

"""
1. 定义DRAM、SSD、HDD的容量和速度：
            容量    速度
    DRAM    4G      100ns
    SSD     500G    150us
    HDD     1T      10ms
"""
# HDD
hdd_size=reader.get_num_of_uniq_req()
hdd_speed=100000
hdd_miss_path="traces/HDD_miss.txt"
# SSD
ssd_size=int(0.5*reader.get_num_of_uniq_req())
ssd_speed=1500
ssd_miss_path="traces/SSD_miss.txt"
# DRAM
dram_size=int(0.004*reader.get_num_of_uniq_req())
if dram_size <1:
    dram_size=1
dram_speed=1
dram_miss_path="traces/DRAM_miss.txt"

"""
2. 定义back_end的HDD，并装入所有的trace数据
"""
# 定义back_end的HDD，其大小能装下所有uniq trace
hdd_cache=LRU(cache_size=hdd_size)
print("hdd size is ",hdd_cache.cache_size)
# 在back_end的HDD中装入全部数据
n_req=reader.get_num_of_req()
evict_item_list = []
for n in range(n_req):
    request=reader.read_one_req()
    req=Req(request)

    if hdd_cache.access(req):
        continue

print("back end hdd_cache info-------------------------------------------")
print(hdd_cache)
print("back end hdd_cache info-------------------------------------------")
reader.reset()


"""
3. 定义2层基于HDD的cache：DRAM-SSD-HDD
    DRAM接受原始trace，后两层均为前一层miss的数据
"""
# 定义函数实现不同cache的配置
def layer_cache(lru_cache,speed,trace_path,miss_path):
    # 以追加写的方式打开miss文件
    miss_file=open(miss_path, mode='a+')

    reader=c.open(trace_path)

    # 获取trace中的行数
    n_req=reader.get_num_of_req()

    # 遍历每一行trace数据
    for n in range(n_req):
        request=reader.read_one_req()
        req=Req(request)
        # print("req's id is",req.item_id)

        # 对应层次的速度进行延迟
        for i in range(speed):
            continue

        if lru_cache.access(req):
            continue
        # 记录导致cache miss
        miss_file.write(req.item_id)
        miss_file.write('\n')

    miss_file.close()

# 计算三层运行的时间
start = time.time()
# 定义三层结构DRAM-SSD-HDD，原始trace依次经过过滤，正确时HDD_miss_file中应该为空
n_layer=0
for n_layer in range(3):
    if n_layer==0:
        # 定义DRAM
        dram_cache=LRU(cache_size=dram_size)
        print("dram cache size is",dram_cache.cache_size)
        layer_cache(dram_cache,dram_speed,trace_path,dram_miss_path)
        dram_end=time.time()
        print("dram time is",dram_end-start)
        print("_____________________________________________________")
        continue
    elif n_layer==1:
        # 定义SSD
        ssd_cache=LRU(cache_size=ssd_size)
        print("ssd cache size is",ssd_cache.cache_size)
        layer_cache(ssd_cache,ssd_speed,dram_miss_path,ssd_miss_path)
        ssd_end=time.time()
        print("ssd time is",ssd_end-dram_end)
        print("_____________________________________________________")
        continue
    else:
        # 定义HDD
        print("enter in hdd")
        layer_cache(hdd_cache,hdd_speed,ssd_miss_path,hdd_miss_path)
        hdd_end=time.time()
        print("hdd time is",hdd_end-ssd_end)

end = time.time()
print("three cache's time is",end-start)


